home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / util / moni / Sysmon120a.lha / sysmon / src / UnMount.c < prev    next >
C/C++ Source or Header  |  2002-08-24  |  8KB  |  293 lines

  1. /*
  2. **    $RCSfile: UnMount.c,v $
  3. **    $Filename: UnMount.c $
  4. **    $Revision: 0.1 $
  5. **    $Date: 1995/04/29 17:33:51 $
  6. **
  7. **    Try to Shutdown or at least Inhibit DOS-Handlers (version 1.1)
  8. **
  9. **    (C) Copyright 1995-2002 by Etienne Vogt
  10. */
  11.  
  12. #include <exec/alerts.h>
  13. #include <exec/memory.h>
  14. #include <dos/dosextens.h>
  15. #include <dos/dostags.h>
  16. #include <dos/filehandler.h>
  17. #include <workbench/startup.h>
  18. #define __USE_SYSBASE
  19. #include <proto/exec.h>
  20. #include <proto/dos.h>
  21. #include <clib/alib_protos.h>
  22. #include <string.h>
  23.  
  24. struct ExecBase *SysBase;
  25. struct DosLibrary *DOSBase;
  26. static struct WBStartup *wbmsg;
  27. static struct RDArgs *myrda;
  28.  
  29. static UBYTE version[] = "$VER: UnMount 1.1 (24.8.2002)";
  30. static UBYTE template[] = "DEVICE,INHIBIT/S,RETRY/K/N,ALL/S,FREENODE/S,QUIET/S";
  31.  
  32. #define DBUFSIZE    16
  33. #define DNAMSIZE    24
  34.  
  35. struct devBuffer
  36. {    struct devBuffer *dbf_Link;
  37.     UBYTE    dbf_Name[DBUFSIZE][DNAMSIZE];
  38. };
  39.  
  40. #define    OPT_DEVICE    0
  41. #define OPT_INHIBIT    1
  42. #define    OPT_RETRY    2
  43. #define OPT_ALL        3
  44. #define OPT_FREENODE    4
  45. #define OPT_QUIET    5
  46. #define OPTMAX        6
  47.  
  48. ULONG __saveds main(void);
  49. static void cleanexit(ULONG rc);
  50. static int unmount(STRPTR device, int inhibit, int retry, int quiet);
  51. static struct devBuffer *getdevices(int *nodes);
  52. static void freedbufs(struct devBuffer *dbufs);
  53. static void killdevices(struct devBuffer *dbuf, int numdevs, int inhibit, int retry, int freenode, int quiet);
  54. static void freeNode(STRPTR device);
  55. static void freeWeird(BPTR bp, ULONG size);
  56.  
  57. ULONG __saveds main(void)    /* No startup code */
  58. {
  59.   struct Process *myproc;
  60.   LONG opts[OPTMAX];
  61.   ULONG rc = 0;
  62.  
  63.   SysBase = *(struct ExecBase **)4;
  64.   DOSBase = NULL;
  65.   wbmsg = NULL;
  66.   myrda = NULL;
  67.  
  68.   myproc = (struct Process *)FindTask(NULL);
  69.   if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",36)) == NULL)
  70.   { Alert(AT_Recovery|AG_OpenLib|AO_DOSLib);
  71.     return 100;
  72.   }
  73.  
  74.   if (!(myproc->pr_CLI))        /* If started from WB, exit cleanly */
  75.   { WaitPort(&(myproc->pr_MsgPort));
  76.     wbmsg = (struct WBStartup *)GetMsg(&(myproc->pr_MsgPort));
  77.     cleanexit(20);
  78.   }
  79.   else
  80.   { APTR oldwinptr;
  81.     int retrycount = 10, error;
  82.  
  83.     memset((char *)opts, 0, sizeof(opts));
  84.     if ((myrda = ReadArgs(template, opts, NULL)) == NULL)
  85.     { PrintFault(IoErr(),"UnMount");
  86.       cleanexit(20);
  87.     }
  88.  
  89.     if (opts[OPT_RETRY]) retrycount = *((LONG *)opts[OPT_RETRY]);
  90.  
  91.     oldwinptr = myproc->pr_WindowPtr;        /* Disable DOS Requesters    */
  92.     myproc->pr_WindowPtr = (APTR)(-1L);
  93.  
  94.     if (opts[OPT_DEVICE])
  95.     { struct DosList *dol;
  96.       char buffer[DNAMSIZE];
  97.       STRPTR colon;
  98.  
  99.       dol = LockDosList(LDF_DEVICES | LDF_READ);
  100.       strncpy(buffer, (STRPTR)opts[OPT_DEVICE], sizeof(buffer));
  101.       if (colon = (UBYTE *)strchr(buffer,':')) *colon = (UBYTE)0;
  102.       else buffer[DNAMSIZE-1] = (UBYTE)0;
  103.       if (dol = FindDosEntry(dol, buffer, LDF_DEVICES))
  104.       { if (dol->dol_Task)    /* There's a handler process running */
  105.     { UnLockDosList(LDF_DEVICES | LDF_READ);
  106.       if (error = unmount((STRPTR)opts[OPT_DEVICE], opts[OPT_INHIBIT], retrycount, opts[OPT_QUIET]))
  107.       { PrintFault(error, "UnMount");
  108.         rc = 10;
  109.       }
  110.     }
  111.     else UnLockDosList(LDF_DEVICES | LDF_READ);
  112.     if (opts[OPT_FREENODE]) freeNode((STRPTR)opts[OPT_DEVICE]);
  113.       }
  114.       else
  115.       { UnLockDosList(LDF_DEVICES | LDF_READ);
  116.     PrintFault(ERROR_DEVICE_NOT_MOUNTED, "UnMount");
  117.     rc = 20;
  118.       }
  119.  
  120.     }
  121.     else if (opts[OPT_ALL])
  122.     { struct devBuffer *dbuf;
  123.       int numdevs;
  124.  
  125.       if (dbuf = getdevices(&numdevs)) killdevices(dbuf, numdevs, opts[OPT_INHIBIT], retrycount, opts[OPT_FREENODE], opts[OPT_QUIET]);
  126.       else
  127.       { PrintFault(ERROR_NO_FREE_STORE, "UnMount");
  128.     rc = 20;
  129.       }
  130.     }
  131.     else
  132.     { PrintFault(ERROR_REQUIRED_ARG_MISSING, "UnMount");
  133.       rc = 20;
  134.     }
  135.  
  136.     myproc->pr_WindowPtr = oldwinptr;
  137.   }
  138.   cleanexit(rc);
  139. }
  140.  
  141. static void cleanexit(ULONG rc)
  142. {
  143.   if (myrda) FreeArgs(myrda);
  144.   if (DOSBase) CloseLibrary((struct Library *)DOSBase);
  145.   if (wbmsg)
  146.   { Forbid();
  147.     ReplyMsg((struct Message *)wbmsg);
  148.   }
  149.   Exit(rc);
  150. }
  151.  
  152. static int unmount(STRPTR device, int inhibit, int retry, int quiet)
  153. { struct DevProc *dvp;
  154.   int count = 0, rc = 0;
  155.  
  156.   if (!strchr(device,':')) return ERROR_INVALID_COMPONENT_NAME;
  157.   if (dvp = GetDeviceProc(device, NULL))
  158.   { if (DoPkt0(dvp->dvp_Port, ACTION_DIE) == DOSFALSE)
  159.     { rc = IoErr();
  160.       if (IsFileSystem(device) && inhibit)
  161.       { if (!quiet) Printf("UnMount: Couldn't kill device %s, Trying to inhibit...\n", device);
  162.     do
  163.     { if (Inhibit(device, DOSTRUE)) break;
  164.       else if ((rc = IoErr()) == ERROR_ACTION_NOT_KNOWN) count = retry;
  165.       else Delay(TICKS_PER_SECOND);
  166.         } while (++count < retry);
  167.     if (count < retry) rc = 0;
  168.       }
  169.     }
  170.     FreeDeviceProc(dvp);
  171.   }
  172.   else rc = IoErr();
  173.   return rc;
  174. }
  175.  
  176. static struct devBuffer *getdevices(int *nodes)
  177. { struct devBuffer *dbuf;
  178.  
  179.   if (dbuf = AllocVec(sizeof(struct devBuffer), MEMF_PUBLIC | MEMF_CLEAR))
  180.   { struct DosList *dol;
  181.     struct devBuffer *db = dbuf;
  182.     int i = 0;
  183.  
  184.     dol = LockDosList(LDF_DEVICES | LDF_READ);
  185.     *nodes = 0;
  186.     while (dol = NextDosEntry(dol, LDF_DEVICES))
  187.     { UBYTE namlen;
  188.       UBYTE *namptr;
  189.  
  190.       if (dol->dol_Task == NULL) continue;
  191.       namptr = BADDR(dol->dol_Name);
  192.       namlen = (namptr[0] < DNAMSIZE - 1 ? namptr[0] : DNAMSIZE - 2);
  193.       strncpy(db->dbf_Name[i], namptr + 1, namlen);
  194.       db->dbf_Name[i][namlen] = ':';
  195.       db->dbf_Name[i][namlen+1] = '\0';
  196.       if (strcmp(db->dbf_Name[i], "RAM:") == 0 || strcmp(db->dbf_Name[i], "ENV:") == 0) continue;
  197.       (*nodes)++;
  198.  
  199.       if (++i == DBUFSIZE)
  200.       { struct devBuffer *db1;
  201.  
  202.     if (db1 = AllocVec(sizeof(struct devBuffer), MEMF_PUBLIC | MEMF_CLEAR))
  203.     { db->dbf_Link = db1;
  204.       db = db1;
  205.       i = 0;
  206.     }
  207.     else
  208.     { UnLockDosList(LDF_DEVICES | LDF_READ);
  209.       freedbufs(dbuf);
  210.       return NULL;
  211.     }
  212.       }
  213.     }
  214.     UnLockDosList(LDF_DEVICES | LDF_READ);
  215.   }
  216.   return dbuf;
  217. }
  218.  
  219. static void freedbufs(struct devBuffer *dbufs)
  220. { struct devBuffer *nextdb;
  221.  
  222.   do
  223.   { nextdb = dbufs->dbf_Link;
  224.     FreeVec(dbufs);
  225.   } while (dbufs = nextdb);
  226. }
  227.  
  228. static void killdevices(struct devBuffer *dbuf, int numdevs, int inhibit, int retry, int freenode, int quiet)
  229. { struct devBuffer *db = dbuf;
  230.   STRPTR devname;
  231.   int j, i, error;
  232.  
  233.   for (j = 0, i = 0 ; j < numdevs ; j++)
  234.   { devname = db->dbf_Name[i];
  235.     if (IsFileSystem(devname))
  236.     { if (!quiet) Printf("Unmounting device %s\n", db->dbf_Name[i]);
  237.       if (error = unmount(devname, inhibit, retry, TRUE) && !quiet) PrintFault(error, "UnMount");
  238.       else if (freenode) freeNode(devname);
  239.     }
  240.  
  241.     if (++i == DBUFSIZE)
  242.     { db = db->dbf_Link;
  243.       i = 0;
  244.     }
  245.   }
  246.   freedbufs(dbuf);
  247. }
  248.  
  249. static void freeNode(STRPTR device)
  250. { struct DosList *dol;
  251.   char buffer[DNAMSIZE];
  252.   STRPTR colon;
  253.   struct FileSysStartupMsg *fssm;
  254.   struct DosEnvec *de;
  255.  
  256.   dol = LockDosList(LDF_DEVICES | LDF_WRITE);
  257.   strncpy(buffer, device, sizeof(buffer));
  258.   if (colon = (UBYTE *)strchr(buffer,':')) *colon = (UBYTE)0;
  259.   else buffer[DNAMSIZE-1] = (UBYTE)0;
  260.   if (dol = FindDosEntry(dol, buffer, LDF_DEVICES))
  261.   { RemDosEntry(dol);
  262.     if (TypeOfMem(fssm = BADDR(dol->dol_misc.dol_handler.dol_Startup)) && ((ULONG)fssm & 1) == 0)
  263.     { de = BADDR(fssm->fssm_Environ);
  264.     /* and now for some extremely bizarre assumptions... */
  265.       if (*(UBYTE *)fssm == 0 || *(UBYTE *)BADDR(fssm->fssm_Device) != 0
  266.     && TypeOfMem(de) != 0 && (de->de_TableSize & 0xffffff00) == 0)
  267.       { if (de->de_TableSize >= DE_CONTROL) freeWeird(de->de_Control, 0);
  268.     freeWeird(fssm->fssm_Device, 0);
  269.     freeWeird(fssm->fssm_Environ, (de->de_TableSize + 1) * sizeof(ULONG));
  270.     freeWeird(dol->dol_misc.dol_handler.dol_Startup, sizeof(struct FileSysStartupMsg));
  271.       }
  272.       else freeWeird(dol->dol_misc.dol_handler.dol_Startup, 0); /* Probably a startup string */
  273.     }
  274.     freeWeird(dol->dol_misc.dol_handler.dol_Handler, 0);
  275.     FreeDosEntry(dol);
  276.   }
  277.   UnLockDosList(LDF_DEVICES | LDF_WRITE);
  278. }
  279.  
  280. /* From Ralph Babel's excellent Guru Book */
  281.  
  282. static void freeWeird(BPTR bp, ULONG size)
  283. { UBYTE *p;
  284.  
  285.   if (bp)
  286.   { p = BADDR(bp);
  287.     if (TypeOfMem(p))    /* Should point to valid memory */
  288.     { if (((ULONG)p & MEM_BLOCKMASK) == 0) FreeMem(p, size != 0 ? size : *p + 2);
  289.       else FreeVec(p); /* Assume BCPL-style memory vector */
  290.     }
  291.   }
  292. }
  293.